package com.hushan.audio;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.TargetDataLine;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * 音频采集管理服务 - 管理音频采集任务的生命周期
 * 使用FFmpeg进行音频采集以获得更好的native模式兼容性
 */
@ApplicationScoped
@Slf4j
public class AudioCaptureManager {
    
    private final Map<String, FFmpegAudioCaptureTask> activeTasks = new ConcurrentHashMap<>();
    private final AtomicLong taskCounter = new AtomicLong(0);
    
    @Inject
    FFmpegDeviceDetector ffmpegDeviceDetector;
    
    /**
     * 启动新的音频采集任务
     */
    public AudioCaptureTaskInfo startCapture(AudioCaptureRequest request) {
        // 生成任务ID
        String taskId = "audio-task-" + taskCounter.incrementAndGet();
        
        // 验证请求参数
        validateRequest(request);
        
        // 生成输出文件名
        String outputFileName = request.getOutputFileName() != null ? 
            request.getOutputFileName() : taskId + ".mp3";
            
        log.info("准备启动FFmpeg音频采集任务: {}", taskId);
        
        // 创建 FFmpeg 音频采集任务
        FFmpegAudioCaptureTask task = new FFmpegAudioCaptureTask(
            taskId,
            outputFileName,
            request.getMixerIndex(), // 作为设备索引使用
            request.getDurationSeconds()
        );
        
        try {
            // 启动异步任务
            task.startAsync();
            
            // 注册任务
            activeTasks.put(taskId, task);
            
            log.info("音频采集任务 {} 启动成功", taskId);
            
            return AudioCaptureTaskInfo.builder()
                .taskId(taskId)
                .outputFileName(outputFileName)
                .mixerIndex(request.getMixerIndex())
                .durationSeconds(request.getDurationSeconds())
                .status("RUNNING")
                .startTime(System.currentTimeMillis())
                .build();
                
        } catch (Exception e) {
            log.error("启动音频采集任务 {} 失败", taskId, e);
            throw new RuntimeException("启动音频采集任务失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 停止指定的FFmpeg音频采集任务
     */
    public boolean stopCapture(String taskId) {
        FFmpegAudioCaptureTask task = activeTasks.get(taskId);
        if (task == null) {
            log.warn("未找到FFmpeg音频采集任务: {}", taskId);
            return false;
        }
        
        try {
            log.info("正在停止音频采集任务: {}", taskId);
            task.stop();
            activeTasks.remove(taskId);
            log.info("音频采集任务 {} 已停止", taskId);
            return true;
        } catch (Exception e) {
            log.error("停止音频采集任务 {} 失败", taskId, e);
            return false;
        }
    }
    
    /**
     * 停止所有音频采集任务
     */
    public void stopAllCaptures() {
        log.info("正在停止所有FFmpeg音频采集任务，当前任务数: {}", activeTasks.size());
        
        activeTasks.values().parallelStream().forEach(task -> {
            try {
                task.stop();
            } catch (Exception e) {
                log.error("停止任务 {} 时发生异常", task.getTaskId(), e);
            }
        });
        
        activeTasks.clear();
        log.info("所有音频采集任务已停止");
    }
    
    /**
     * 获取FFmpeg任务信息
     */
    public AudioCaptureTaskInfo getTaskInfo(String taskId) {
        FFmpegAudioCaptureTask task = activeTasks.get(taskId);
        if (task == null) {
            return null;
        }
        
        return AudioCaptureTaskInfo.builder()
            .taskId(taskId)
            .outputFileName(task.getOutputFileName())
            .status(task.isRunning() ? "RUNNING" : "STOPPED")
            .build();
    }
    
    /**
     * 获取所有活动FFmpeg任务的信息
     */
    public List<AudioCaptureTaskInfo> getAllTasksInfo() {
        return activeTasks.values().stream()
            .map(task -> AudioCaptureTaskInfo.builder()
                .taskId(task.getTaskId())
                .outputFileName(task.getOutputFileName())
                .status(task.isRunning() ? "RUNNING" : "STOPPED")
                .build())
            .collect(Collectors.toList());
    }
    
    /**
     * 获取可用的音频混音器列表
     * 优先使用FFmpeg设备检测，Java Sound API作为后备
     */
    public List<AudioMixerInfo> getAvailableMixers() {
        // 1. 首先尝试FFmpeg设备检测
        try {
            if (ffmpegDeviceDetector.isFFmpegDeviceDetectionAvailable()) {
                log.info("使用FFmpeg进行音频设备检测");
                List<AudioMixerInfo> ffmpegDevices = ffmpegDeviceDetector.getAudioInputDevices();
                
                if (!ffmpegDevices.isEmpty()) {
                    log.info("FFmpeg成功检测到 {} 个音频设备", ffmpegDevices.size());
                    return ffmpegDevices;
                } else {
                    log.warn("FFmpeg检测到的设备列表为空，尝试Java Sound API");
                }
            } else {
                log.warn("FFmpeg设备检测不可用，使用Java Sound API");
            }
        } catch (Exception e) {
            log.error("FFmpeg设备检测失败，回退到Java Sound API", e);
        }
        
        // 2. 回退到Java Sound API
        return getJavaSoundMixers();
    }
    
    /**
     * 使用Java Sound API获取混音器列表
     */
    private List<AudioMixerInfo> getJavaSoundMixers() {
        try {
            Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
            
            if (mixerInfos == null || mixerInfos.length == 0) {
                log.warn("AudioSystem.getMixerInfo() 返回空结果，可能是native模式下的已知问题");
                log.info("尝试检测默认混音器可用性...");
                
                // 尝试检测默认混音器是否可用
                boolean defaultMixerWorks = testDefaultMixer();
                return getDefaultMixerInfos(defaultMixerWorks);
            }
            
            log.info("Java Sound API成功检测到 {} 个音频混音器", mixerInfos.length);
            return java.util.Arrays.stream(mixerInfos)
                .map(mixerInfo -> AudioMixerInfo.builder()
                    .index(java.util.Arrays.asList(mixerInfos).indexOf(mixerInfo))
                    .name(mixerInfo.getName())
                    .description(mixerInfo.getDescription())
                    .vendor(mixerInfo.getVendor())
                    .version(mixerInfo.getVersion())
                    .build())
                .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取音频混音器信息失败，使用默认配置", e);
            boolean defaultMixerWorks = testDefaultMixer();
            return getDefaultMixerInfos(defaultMixerWorks);
        }
    }
    
    /**
     * 测试默认混音器是否可用
     */
    private boolean testDefaultMixer() {
        try {
            // 尝试获取默认混音器
            Mixer defaultMixer = AudioSystem.getMixer(null);
            if (defaultMixer == null) {
                log.warn("默认混音器为null");
                return false;
            }
            
            // 尝试创建音频输入线
            AudioFormat audioFormat = new AudioFormat(
                AudioFormat.Encoding.PCM_SIGNED, 44100f, 16, 2, 4, 44100f, false);
            DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
            
            if (defaultMixer.isLineSupported(dataLineInfo)) {
                log.info("默认混音器支持音频输入");
                return true;
            } else {
                log.warn("默认混音器不支持所需的音频格式");
                return false;
            }
        } catch (Exception e) {
            log.warn("测试默认混音器失败: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 获取默认的混音器信息（用于native模式下的后备方案）
     */
    private List<AudioMixerInfo> getDefaultMixerInfos(boolean defaultMixerWorks) {
        log.info("使用默认音频混音器配置（默认混音器可用: {}）", defaultMixerWorks);
        
        if (defaultMixerWorks) {
            return List.of(
                AudioMixerInfo.builder()
                    .index(0)
                    .name("Default System Audio (Native Mode)")
                    .description("Default system audio capture device - working")
                    .vendor("System")
                    .version("1.0")
                    .build()
            );
        } else {
            return List.of(
                AudioMixerInfo.builder()
                    .index(0)
                    .name("Default System Audio (Fallback)")
                    .description("Audio capture may not work - native mode limitation")
                    .vendor("System")
                    .version("1.0")
                    .build()
            );
        }
    }
    
    /**
     * 清理已完成的任务
     */
    public int cleanupCompletedTasks() {
        int cleanedCount = 0;
        
        activeTasks.entrySet().removeIf(entry -> {
            FFmpegAudioCaptureTask task = entry.getValue();
            if (!task.isRunning()) {
                log.debug("清理已完成的FFmpeg任务: {}", entry.getKey());
                return true;
            }
            return false;
        });
        
        return cleanedCount;
    }
    
    /**
     * 验证请求参数
     */
    private void validateRequest(AudioCaptureRequest request) {
        if (request.getMixerIndex() < 0) {
            throw new IllegalArgumentException("混音器索引不能为负数");
        }
        
        if (request.getDurationSeconds() <= 0) {
            throw new IllegalArgumentException("录音时长必须大于0");
        }
        
        if (request.getDurationSeconds() > 3600) {
            throw new IllegalArgumentException("录音时长不能超过3600秒");
        }
        
        // 验证混音器是否存在（在native模式下可能无法获取）
        try {
            Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
            if (mixerInfos != null && mixerInfos.length > 0) {
                if (request.getMixerIndex() >= mixerInfos.length) {
                    throw new IllegalArgumentException("混音器索引超出范围: " + request.getMixerIndex());
                }
            } else {
                // native模式下的后备验证，只允许使用限定的索引
                if (request.getMixerIndex() > 10) { // 允许最多10个设备索引
                    log.warn("Native模式下无法验证混音器索引，但索引 {} 超出合理范围", request.getMixerIndex());
                    throw new IllegalArgumentException("混音器索引超出合理范围: " + request.getMixerIndex());
                }
                log.info("Native模式下无法验证混音器索引，将在运行时检查");
            }
        } catch (Exception e) {
            log.warn("无法获取混音器信息进行验证，将在运行时检查: {}", e.getMessage());
        }
    }
    
    /**
     * 获取当前活动任务数量
     */
    public int getActiveTaskCount() {
        return activeTasks.size();
    }
    
    /**
     * 检查FFmpeg任务是否存在且运行中
     */
    public boolean isTaskRunning(String taskId) {
        FFmpegAudioCaptureTask task = activeTasks.get(taskId);
        return task != null && task.isRunning();
    }
}